"""
工具函数模块
"""
import os
import yaml
import logging
import pandas as pd
from typing import Dict, List, Any
import random
import time
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
import jieba
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity


def load_config(config_path: str = "config/config.yaml") -> Dict[str, Any]:
    """
    加载配置文件
    
    Args:
        config_path: 配置文件路径
    
    Returns:
        配置字典
    """
    try:
        with open(config_path, 'r', encoding='utf-8') as file:
            config = yaml.safe_load(file)
        return config
    except FileNotFoundError:
        raise FileNotFoundError(f"配置文件未找到: {config_path}")
    except yaml.YAMLError as e:
        raise ValueError(f"配置文件格式错误: {e}")


def setup_logging(config: Dict[str, Any]) -> logging.Logger:
    """
    设置日志配置
    
    Args:
        config: 配置字典
    
    Returns:
        logger对象
    """
    log_config = config.get('logging', {})
    level = getattr(logging, log_config.get('level', 'INFO'))
    format_str = log_config.get('format', '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    log_file = log_config.get('file', 'logs/keyword_mining.log')
    
    # 确保日志目录存在
    os.makedirs(os.path.dirname(log_file), exist_ok=True)
    
    logging.basicConfig(
        level=level,
        format=format_str,
        handlers=[
            logging.FileHandler(log_file, encoding='utf-8'),
            logging.StreamHandler()
        ]
    )
    
    return logging.getLogger(__name__)


def save_data(data: pd.DataFrame, filename: str, formats: List[str] = None, 
              save_path: str = "data/results") -> None:
    """
    保存数据到不同格式的文件
    
    Args:
        data: 要保存的数据
        filename: 文件名（不含扩展名）
        formats: 保存格式列表
        save_path: 保存路径
    """
    if formats is None:
        formats = ["csv"]
    
    # 确保保存目录存在
    os.makedirs(save_path, exist_ok=True)
    
    for fmt in formats:
        filepath = os.path.join(save_path, f"{filename}.{fmt}")
        
        if fmt == "csv":
            data.to_csv(filepath, index=False, encoding='utf-8-sig')
        elif fmt == "xlsx":
            data.to_excel(filepath, index=False, engine='openpyxl')
        elif fmt == "json":
            data.to_json(filepath, orient='records', force_ascii=False, indent=2)
        
        print(f"数据已保存至: {filepath}")


def random_delay(delay_range: List[float]) -> None:
    """
    随机延迟
    
    Args:
        delay_range: 延迟范围 [min, max]
    """
    delay = random.uniform(delay_range[0], delay_range[1])
    time.sleep(delay)


def clean_text(text: str) -> str:
    """
    基本文本清洗
    
    Args:
        text: 原始文本
    
    Returns:
        清洗后的文本
    """
    if not isinstance(text, str):
        return ""
    
    # 去除首尾空白
    text = text.strip()
    
    # 替换多个空格为单个空格
    import re
    text = re.sub(r'\s+', ' ', text)
    
    return text


def ensure_dir(directory: str) -> None:
    """
    确保目录存在
    
    Args:
        directory: 目录路径
    """
    os.makedirs(directory, exist_ok=True)


def get_user_agent() -> str:
    """
    获取随机User-Agent
    
    Returns:
        User-Agent字符串
    """
    user_agents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    ]
    return random.choice(user_agents)


def send_email_notification(
    subject: str,
    content: str,
    config: Dict[str, Any],
    to_emails: List[str] = None
) -> bool:
    """
    发送邮件通知
    
    Args:
        subject: 邮件主题
        content: 邮件内容
        config: 配置字典
        to_emails: 收件人邮箱列表
    
    Returns:
        是否发送成功
    """
    try:
        email_config = config.get('fresh_topic_discovery', {}).get('email', {})
        
        if not email_config.get('enabled', False):
            logging.info("邮件通知功能未启用")
            return False
        
        # 使用配置中的收件人，如果没有则使用传入的
        if to_emails is None:
            to_emails = email_config.get('to_emails', [])
        
        if not to_emails:
            logging.warning("没有指定收件人邮箱")
            return False
        
        # 创建邮件
        msg = MIMEMultipart()
        msg['From'] = f"{email_config.get('from_name', '新鲜需求发现小助手')} <{email_config['username']}>"
        msg['To'] = ', '.join(to_emails)
        msg['Subject'] = Header(subject, 'utf-8')
        
        # 添加邮件内容
        text_part = MIMEText(content, 'html', 'utf-8')
        msg.attach(text_part)
        
        # 连接SMTP服务器
        server = smtplib.SMTP(email_config['smtp_server'], email_config['smtp_port'])
        server.starttls()
        server.login(email_config['username'], email_config['password'])
        
        # 发送邮件
        server.sendmail(email_config['username'], to_emails, msg.as_string())
        server.quit()
        
        logging.info(f"邮件发送成功: {subject}")
        return True
        
    except Exception as e:
        logging.error(f"邮件发送失败: {e}")
        return False


def calculate_text_similarity(text1: str, text2: str) -> float:
    """
    计算两段文本的相似度
    
    Args:
        text1: 文本1
        text2: 文本2
    
    Returns:
        相似度分数 (0-1)
    """
    try:
        # 分词
        words1 = ' '.join(jieba.cut(text1))
        words2 = ' '.join(jieba.cut(text2))
        
        # 使用TF-IDF向量化
        vectorizer = TfidfVectorizer()
        tfidf_matrix = vectorizer.fit_transform([words1, words2])
        
        # 计算余弦相似度
        similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])[0][0]
        
        return float(similarity)
        
    except Exception as e:
        logging.error(f"计算文本相似度失败: {e}")
        return 0.0


def find_similar_topics(
    new_topic: str,
    existing_topics: List[str],
    threshold: float = 0.8
) -> List[tuple]:
    """
    在已有话题中查找相似的话题
    
    Args:
        new_topic: 新话题
        existing_topics: 已有话题列表
        threshold: 相似度阈值
    
    Returns:
        相似话题列表 [(话题, 相似度)]
    """
    similar_topics = []
    
    for existing_topic in existing_topics:
        similarity = calculate_text_similarity(new_topic, existing_topic)
        if similarity >= threshold:
            similar_topics.append((existing_topic, similarity))
    
    # 按相似度排序
    similar_topics.sort(key=lambda x: x[1], reverse=True)
    
    return similar_topics


def is_fresh_topic(
    new_topic: str,
    existing_topics: List[str],
    threshold: float = 0.8
) -> bool:
    """
    判断是否为新话题
    
    Args:
        new_topic: 新话题
        existing_topics: 已有话题列表
        threshold: 相似度阈值
    
    Returns:
        是否为新话题
    """
    similar_topics = find_similar_topics(new_topic, existing_topics, threshold)
    return len(similar_topics) == 0


def format_email_content(
    new_topics: List[Dict[str, Any]],
    search_keyword: str,
    search_round: int
) -> str:
    """
    格式化邮件内容
    
    Args:
        new_topics: 新话题列表
        search_keyword: 搜索关键词
        search_round: 搜索轮数
    
    Returns:
        格式化的HTML邮件内容
    """
    html_content = f"""
    <html>
    <head>
        <meta charset="utf-8">
        <style>
            body {{ font-family: Arial, sans-serif; margin: 20px; }}
            .header {{ background-color: #f0f8ff; padding: 15px; border-radius: 5px; }}
            .topic-item {{ margin: 10px 0; padding: 10px; border-left: 4px solid #007acc; background-color: #f9f9f9; }}
            .keyword {{ color: #007acc; font-weight: bold; }}
            .source {{ color: #666; font-size: 12px; }}
            .stats {{ background-color: #e8f4f8; padding: 10px; border-radius: 5px; margin: 15px 0; }}
        </style>
    </head>
    <body>
        <div class="header">
            <h2>🎯 新鲜需求发现通知</h2>
            <p>发现新的有价值话题，可能与您的业务相关！</p>
        </div>
        
        <div class="stats">
            <h3>📊 搜索统计</h3>
            <p><strong>搜索关键词:</strong> <span class="keyword">{search_keyword}</span></p>
            <p><strong>搜索轮数:</strong> {search_round}</p>
            <p><strong>新话题数量:</strong> {len(new_topics)}</p>
            <p><strong>发现时间:</strong> {new_topics[0]['created_at'] if new_topics else 'N/A'}</p>
        </div>
        
        <h3>🆕 新发现的话题</h3>
    """
    
    for i, topic in enumerate(new_topics, 1):
        html_content += f"""
        <div class="topic-item">
            <h4>话题 {i}: {topic['topic_text']}</h4>
            <p><strong>来源关键词:</strong> <span class="keyword">{topic['source_keyword']}</span></p>
            <p><strong>搜索引擎:</strong> {topic['search_source']}</p>
            <p><strong>搜索轮数:</strong> {topic['search_round']}</p>
            <p class="source">发现时间: {topic['created_at']}</p>
        </div>
        """
    
    html_content += """
        <div style="margin-top: 20px; padding: 15px; background-color: #f0f8ff; border-radius: 5px;">
            <p><strong>💡 提示:</strong></p>
            <ul>
                <li>这些话题可能代表新的市场需求或用户关注点</li>
                <li>建议及时分析这些话题的商业价值</li>
                <li>可以考虑基于这些话题开发新的产品或服务</li>
            </ul>
        </div>
        
        <div style="margin-top: 20px; text-align: center; color: #666;">
            <p>此邮件由新鲜需求发现小助手自动发送</p>
            <p>如有疑问，请联系系统管理员</p>
        </div>
    </body>
    </html>
    """
    
    return html_content


def get_logger(name: str = "fresh_topic_discovery") -> logging.Logger:
    """
    获取日志记录器
    
    Args:
        name: 日志记录器名称
    
    Returns:
        日志记录器
    """
    logger = logging.getLogger(name)
    
    if not logger.handlers:
        logger.setLevel(logging.INFO)
        
        # 创建控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        
        # 创建文件处理器
        file_handler = logging.FileHandler(f"logs/{name}.log", encoding='utf-8')
        file_handler.setLevel(logging.INFO)
        
        # 设置格式
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        console_handler.setFormatter(formatter)
        file_handler.setFormatter(formatter)
        
        logger.addHandler(console_handler)
        logger.addHandler(file_handler)
    
    return logger